/* Bugzilla C# Proxy Library
   Copyright (C) 2006, Dansk BiblioteksCenter A/S
   Mads Bondo Dydensborg, <mbd@dbc.dk>
   
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.
   
   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.
   
   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

/*! \file
  \brief Definition of the methods supported by the Bugzilla WebService module.
  
  The definitions are used by the xml-rpc.net framework. User should
  use the IServer interface in the Bugzilla namespace instead.

  The purpose of this file is to define the proxy interface for use
  by xml-rpc. The xml-rpc interface of bugzilla is in essence a flat
  interface of functions, with names suggesting some kind of
  coherence between the different functions.

  Bugzilla's authentication system is based on cookies. This can be
  handled by the xml-rpc.net system. In order to make it as easy as
  possibly, all interface functions are attached to the same proxy.
  At the C# interface level, functions are named following C# sharp
  standard. The XmlRpcMethod attribute before each function tells
  which bugzilla RPC method is actually called by the interface.

  The standard of the %Bugzilla webservice is to have functions that
  takes parameters use a struct (perl:hash) and values returned, also
  return a struct (or nothing). In this interface this is organized by
  having each function (that takes a parameter) take a struct called
  param, of a type that is named after the function. Return types are
  likewise named after the method. So, e.g. "Login" uses a parameter
  type called "LoginParam", and returns a type called LoginResult.
  The meaning of these parameter and result types are described using
  C# inline docs in the actual structs.
*/

using CookComputing.XmlRpc;
using System;

namespace BugzProxy
{
    using ProxyStructs;

    namespace ProxyStructs
    {

        //////////////////////////////////////////////////////////////////////
        // Version and timezone

        /// <summary>Result for call to <see cref="IProxy.GetVersion"/>.</summary>
        public struct GetVersionResult
        {
            /// <summary>The version of the server, as a string</summary>
            public string version;
        }

        /// <summary>Result for call to <see cref="IProxy.GetTimezone"/></summary>
        public struct GetTimezoneResult
        {
            /// <summary>The timezone information as a string, in RFC 2822 format</summary>
            [XmlRpcMember("timezone")]
            public string timeZone;
        }

        /// <summary>
        /// Result of call to <see cref="IProxy.GetPlugins"/>.
        /// </summary>
        public struct GetPluginsResult
        {
            /// <summary>
            /// A hashtable with plugin names as keys, and versions as values.
            /// </summary>
            public XmlRpcStruct plugins;
        }

        //////////////////////////////////////////////////////////////////////
        // Login handling

        /// <summary>Parameter struct for the <see cref="IProxy.Login"/> method</summary>
        public struct LoginParam
        {
            /// <summary>The user's login e-mail</summary>
            public string login;
            /// <summary>The user's password</summary>
            public string password;
            /// <summary>If the bugzilla server allow cookie session management, 
            /// then this option determines if the cookies issued by the server 
            /// can survive between sessions</summary>
            [XmlRpcMissingMapping(MappingAction.Ignore)]
            public bool? remember;
        }
        /// <summary>Parameter struct for the result of the <see cref="IProxy.Login"/>
        /// method</summary>
        public struct LoginResult
        {
            /// <summary>The numeric id of the user upon successful login</summary>
            public int id;
        }


        //////////////////////////////////////////////////////////////////////
        // Product handling

        /// <summary>A list of product ids. This is used in several methods, 
        /// both as a param and as a result type</summary>
        public struct ProductIds
        {
            /// <summary>Array of product ids</summary>
            public int[] ids;
        }

        /// <summary>Information about a single product.</summary>
        public struct ProductInfo
        {
            /// <summary>Internal information from the server about the product. 
            /// This can and will change frequently</summary>
            public XmlRpcStruct internals;
            /// <summary>Product nummeric id</summary>
            public int id;
            /// <summary>Product name</summary>
            public string name;
            /// <summary>Product description</summary>
            public string description;
        }

        /// <summary>A list of Products</summary>
        public struct GetProductsResult
        {
            /// <summary>Array of Products</summary>
            public ProductInfo[] products;
        }

        //////////////////////////////////////////////////////////////////////
        // Bug handling

        /// <summary>A list of bug ids. This is used in several functions, 
        /// both as a param and as a result type</summary>
        public struct BugIds
        {
            /// <summary>Array of bug ids</summary>
            public int[] ids;
        }

        /// <summary>Information about a single bug.</summary>
        public struct BugInfo
        {
            /// <summary>Internal information from the server about the bug. 
            /// This can and will change frequently</summary>
            public XmlRpcStruct internals;
            /// <summary>Bug nummeric id</summary>
            public int id;
            /// <summary>Bug alias (empty string if no aliases)</summary>
            public string alias;
            /// <summary>Bug summary</summary>
            public string summary;
            /// <summary>Time/date when bug was created</summary>
            [XmlRpcMember("creation_time")]
            public DateTime created;
            /// <summary>Time/date when bug was last changed</summary>
            [XmlRpcMember("last_change_time")]
            public DateTime changed;
        }

        /// <summary>A list of Bugs</summary>
        public struct GetBugsResult
        {
            /// <summary>Array of Bugs</summary>
            public BugInfo[] bugs;
        }

        /// <summary>Information needed to create a bug</summary>
        public struct CreateBugParam
        {
            /// <summary>Name of product to create bug against</summary>
            public string product;
            /// <summary>Name of component to create bug against</summary>
            public string component;
            /// <summary>Summary of bug</summary>
            public string summary;
            /// <summary>Version of product above, the version the bug was found in</summary>
            public string version;
            /// <summary>The initial description for this bug. Some %Bugzilla
            /// installations require this to not be blank.</summary>
            [XmlRpcMissingMapping(MappingAction.Ignore)]
            public string description;
            /// <summary>The operating system the bug was discovered
            /// on. Some %Bugzilla installations require this to not be
            /// blank.</summary>
            [XmlRpcMissingMapping(MappingAction.Ignore)]
            [XmlRpcMember("op_sys")]
            public string operatingSystem;
            /// <summary>What type of hardware the bug was experienced
            /// on. Some %Bugzilla installations require this to not be
            /// blank.</summary>
            [XmlRpcMissingMapping(MappingAction.Ignore)]
            public string platform;
            /// <summary>What order the bug will be fixed in by the
            /// developer, compared to the developers other bugs. Some
            /// %Bugzilla installations require this to not be
            /// blank. </summary>
            [XmlRpcMissingMapping(MappingAction.Ignore)]
            public string priority;
            /// <summary>How severe the bug is. Some %Bugzilla installations
            /// require this to not be blank. </summary>
            [XmlRpcMissingMapping(MappingAction.Ignore)]
            public string severity;
            /// <summary>A brief alias for the bug that can be used instead
            /// of a bug number when accessing this bug. Must be unique in
            /// all of this %Bugzilla.</summary>
            [XmlRpcMissingMapping(MappingAction.Ignore)]
            public string alias;
            /// <summary>A user to assign this bug to, if you dont want it
            /// to be assigned to the component owner.</summary>
            [XmlRpcMissingMapping(MappingAction.Ignore)]
            [XmlRpcMember("assigned_to")]
            public string assignedTo;
            /// <summary>An array of usernames to CC on this bug.</summary>
            [XmlRpcMissingMapping(MappingAction.Ignore)]
            public string[] cc;
            /// <summary>If this installation has QA Contacts enabled, you
            /// can set the QA Contact here if you don't want to use the
            /// component's default QA Contact.</summary>
            [XmlRpcMissingMapping(MappingAction.Ignore)]
            [XmlRpcMember("qa_contact")]
            public string qaContact;
            /// <summary>The status that this bug should start out as. Note
            /// that only certain statuses can be set on bug creation.</summary>
            [XmlRpcMissingMapping(MappingAction.Ignore)]
            public string status;
            /// <summary>A valid target milestone for this product.</summary>
            [XmlRpcMissingMapping(MappingAction.Ignore)]
            [XmlRpcMember("target_milestone")]
            public string targetMilestone;
        }

        /// <summary>Result of call to <see cref="IProxy.CreateBug"/></summary>
        public struct CreateBugResult
        {
            /// <summary>The id of the newly created bug</summary>
            public int id;
        }

        // Legal values for fields of a bug
        /// <summary>Parameter for <see cref="IProxy.GetLegalValuesForBugField"/> call.</summary>
        public struct GetLegalValuesForBugFieldParam
        {
            /// <summary>Which field to query for</summary>
            public string field;
            /// <summary>If the field is product specific, which product then</summary>
            [XmlRpcMember("product_id")]
            public int productId;
        }

        /// <summary>Result of call to <see cref="IProxy.GetLegalValuesForBugField"/>
        /// </summary>
        public struct GetLegalValuesForBugFieldResult
        {
            /// <summary>Array of values</summary>
            public string[] values;
        }

        /// <summary>Parameter for <see cref="IProxy.AppendComment"/> call</summary>
        public struct AppendCommentParam
        {
            /// <summary>The id of the bug</summary>
            public int id;
            /// <summary>The actual comment to append</summary>
            public string comment;
            /// <summary>Whether or not this is a private comment.</summary>
            /// <remarks>This is ignored if you are not in the <i>insidergroup</i>.
            /// </remarks>
            // Note, must use renaming, as "private" is reserved in C#.
            [XmlRpcMissingMapping(MappingAction.Ignore)]
            [XmlRpcMember("private")]
            public bool? isPrivate;
            /// <summary>The worktime of this comment.</summary>
            [XmlRpcMissingMapping(MappingAction.Ignore)]
            [XmlRpcMember("work_time")]
            public double? workTime;
        }

        /// <summary>Parameter for call to <see cref="IProxy.SetBugResolution"/></summary>
        public struct SetBugResolutionParam
        {
            /// <summary>The id of the bug</summary>
            [XmlRpcMember("bug_id")]
            public int bugId;
            /// <summary>The actual resolution to set. Should be legal.</summary>
            public string resolution;
        }

    } // namespace ProxyStructs

    /// <summary>The interface for use by the xml-rpc.net framework.</summary>
    /// <remarks>The interface methods translate
    /// into other method names at the server end, as we are using
    /// .NET name styling. It also puts all methods in the same
    /// interface. This may change. Users are not expected to use this
    /// interface directly.</remarks>
    public interface IProxy : IXmlRpcProxy
    {

        //////////////////////////////////////////////////////////////////////
        // Server related / general methods
        //////////////////////////////////////////////////////////////////////

        /*! \name General Methods */
        //@{

        //////////////////////////////////////////////////////////////////////
        /// <summary>Get the version of the server</summary>
        /// <returns>The version of the server as a string</returns>
        [XmlRpcMethod("Bugzilla.version")]
        GetVersionResult GetVersion();

        //////////////////////////////////////////////////////////////////////
        /// <summary>Get the timezone of the server</summary>
        /// <returns>The timezone information as a string, in RFC 2822 format</returns>
        [XmlRpcMethod("Bugzilla.timezone")]
        GetTimezoneResult GetTimezone();

        /// <summary>
        /// Get a list of currently installed plugins on the server, and each plugin's
        /// version.
        /// </summary>
        /// <remarks>Works with Bugzilla 3.1.2+ only.</remarks>
        /// <returns>A <see cref="GetPluginsResult"/>, with a hashtable with plugin
        /// names as keys, and their versions as values.</returns>
        [XmlRpcMethod("Bugzilla.plugins")]
        GetPluginsResult GetPlugins();

        //@}

        /*! \name Login/out */
        //@{
        //////////////////////////////////////////////////////////////////////
        /// <summary>Login to the server</summary> 
        /// <param name="param">Login, password and optional remember value</param>
        /// <returns>If successful, the user's numeric id</returns>
        [XmlRpcMethod("User.login")]
        LoginResult Login(LoginParam param);

        //////////////////////////////////////////////////////////////////////
        /// <summary>Logout of the server</summary>
        [XmlRpcMethod("User.logout")]
        void Logout();
        //@}

        //////////////////////////////////////////////////////////////////////
        // Product related methods
        //////////////////////////////////////////////////////////////////////
        /*! \name Product Related Methods */
        //@{
        //////////////////////////////////////////////////////////////////////
        /// <summary>Get a list of the products (ids) that the user can
        /// search against.</summary>
        /// <returns>A list of product ids</returns>
        [XmlRpcMethod("Product.get_selectable_products")]
        ProductIds GetSelectableProducts();

        //////////////////////////////////////////////////////////////////////
        /// <summary>Get a list of the products (ids) that the user can
        /// post bugs against.</summary>
        /// <returns>A list of product ids</returns>
        [XmlRpcMethod("Product.get_enterable_products")]
        ProductIds GetEnterableProducts();

        //////////////////////////////////////////////////////////////////////
        /// <summary>Get a list of the products (ids) that the user can
        /// search or enter bug against.</summary>
        /// <returns>A list of product ids</returns>
        [XmlRpcMethod("Product.get_accessible_products")]
        ProductIds GetAccessibleProducts();

        //////////////////////////////////////////////////////////////////////
        /// <summary>Get a list of products from a list of ids</summary>
        /// <param name="param">A list of product ids</param>
        /// <returns>A list of products</returns>
        [XmlRpcMethod("Product.get_products")]
        GetProductsResult GetProducts(ProductIds param);
        //@}

        //////////////////////////////////////////////////////////////////////
        // Bug related methods
        //////////////////////////////////////////////////////////////////////
        /*! \name Bug Related Methods */
        //@{

        //////////////////////////////////////////////////////////////////////
        /// <summary>Create a new bug</summary>
        /// <param name="param">Various information about the new bug</param>
        /// <returns>The id of the newly created bug</returns>
        [XmlRpcMethod("Bug.create")]
        CreateBugResult CreateBug(CreateBugParam param);

        //////////////////////////////////////////////////////////////////////
        /// <summary>Get a list of bugs from a list of ids</summary>
        /// <param name="param">A list of bug ids</param>
        /// <returns>A list of bugs</returns>
        [XmlRpcMethod("Bug.get_bugs")]
        GetBugsResult GetBugs(BugIds param);

        //////////////////////////////////////////////////////////////////////
        /// <summary>Get a list of legal values for a field in a bug</summary>
        /// <param name="param">Which field, possibly product</param>
        /// <returns>The legal values for the field</returns>
        [XmlRpcMethod("Bug.legal_values")]
        GetLegalValuesForBugFieldResult GetLegalValuesForBugField(GetLegalValuesForBugFieldParam param);

        //@}

        /*! \name Experimental Methods
          These are here as part of the development of patches, etc. */
        //@{

        //////////////////////////////////////////////////////////////////////
        /// <summary>Append a comment</summary>
        /// <remarks>Works with Bugzilla trunk (3.1.2+) only</remarks>
        /// <param name="param">Bug id, comment, etc</param>
        [XmlRpcMethod("Bug.add_comment")]
        void AppendComment(AppendCommentParam param);

        //////////////////////////////////////////////////////////////////////
        /// <summary>Change the resolution of a bug</summary>
        /// <remarks>This requires an unpublished patch</remarks>
        /// <param name="param">Bug id and resolution</param>
        [XmlRpcMethod("Bug.set_resolution")]
        string SetBugResolution(SetBugResolutionParam param);

        //@}
    }
} // namespace
